package com.kvest.maputils;

import android.util.Log;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: Kvest
 * Date: 17.04.13
 * Time: 21:34
 * To change this template use File | Settings | File Templates.
 */
public class PathFinder {
    private static final String URL = "http://maps.googleapis.com/maps/api/directions/json";
    private static final String START_POINT_PARAM = "origin";
    private static final String END_POINT_PARAM = "destination";
    private static final String SENSOR_POINT_PARAM = "sensor";
    private static final String MODE_PARAM = "mode";

    private Coordinate startPoint;
    private Coordinate endPoint;

    public PathFinder(Coordinate startPoint, Coordinate endPoint) {
        this.startPoint = startPoint;
        this.endPoint = endPoint;
    }

    public FindPathResult findPath() throws IOException {
        String json = getPathJSON();
        FindPathResult path = parseJson(json);
        return path;
    }

    private String generateURL() {
        StringBuilder sb = new StringBuilder();
        sb.append(URL);
        sb.append("?");
        //start point
        sb.append(START_POINT_PARAM);
        sb.append("=");
        sb.append(startPoint.toString());
        sb.append("&");
        //end point
        sb.append(END_POINT_PARAM);
        sb.append("=");
        sb.append(endPoint.toString());
        sb.append("&");
        //sensor
        sb.append(SENSOR_POINT_PARAM);
        sb.append("=true");
        sb.append("&");
        //mode (значение по умолчанию – driving)
        sb.append(MODE_PARAM);
        sb.append("=driving");

        return sb.toString();
    }

    private String getPathJSON() throws IOException {
        //Create request
        HttpGet httpRequest = new HttpGet(generateURL());

        //Execute request
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpResponse httpResponse = httpClient.execute(httpRequest);

        //Get result
        String rawResponse = null;
        int status = httpResponse.getStatusLine().getStatusCode();
        if ((status / 10) == 20 /* All 20x statuses*/) {
            rawResponse = EntityUtils.toString(httpResponse.getEntity());
        }

        httpClient.getConnectionManager().closeExpiredConnections();

        return rawResponse;
    }

    private FindPathResult parseJson(String json) {
        FindPathResult result = new FindPathResult();
        result.setFound(false);
        try {
            JSONObject root = new JSONObject(json);
            //check if request is successful
            if (!(root.has("status") && root.getString("status").toLowerCase().equals("ok"))) {
                return result;
            }

            //get routes
            JSONArray routes = root.getJSONArray("routes");
            if (routes.length() == 0) {
                return result;
            }

            //get legs
            JSONArray legs = routes.getJSONObject(0).getJSONArray("legs");
            if (legs.length() == 0) {
                return result;
            }

            //first leg
            JSONObject firstLeg = legs.getJSONObject(0);

            //get distance
            result.setDistance(firstLeg.getJSONObject("distance").getInt("value"));

            //start point
            result.addPoint(parseCoordinate(firstLeg.getJSONObject("start_location")));

            //steps
            JSONArray steps = firstLeg.getJSONArray("steps");
            for (int i = 0; i < steps.length(); ++i) {
                result.addPoint(parseCoordinate(steps.getJSONObject(i).getJSONObject("end_location")));
            }

            result.setFound(true);
        } catch (JSONException jsonException) { }
        return result;
    }

    private Coordinate parseCoordinate(JSONObject jsonObj) throws JSONException {
        return new Coordinate(jsonObj.getDouble("lat"), jsonObj.getDouble("lng"));
    }

    public Coordinate getStartPoint() {
        return startPoint;
    }

    public void setStartPoint(Coordinate startPoint) {
        this.startPoint = startPoint;
    }

    public Coordinate getEndPoint() {
        return endPoint;
    }

    public void setEndPoint(Coordinate endPoint) {
        this.endPoint = endPoint;
    }
}
